package com.tnsw.noxnox.streamer;

import java.io.File;
import java.io.FileInputStream;
import java.net.Socket;
import java.util.ArrayList;

import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.message.BasicHeader;

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import com.tnsw.coreutils.AsyncManager;
import com.tnsw.noxnox.db.DBManager;
import com.tnsw.noxnox.db.tables.DownloadProgress;
import com.tnsw.noxnox.settopbox.STBHttpBuilderBase;

public class MediaCustomHandler extends STBHttpBuilderBase {

	private String tag = "MediaCustomHandler";
	private DBManager dbm;
	private AsyncManager asyncManager;
	
	public MediaCustomHandler(Context context, Socket socket) {
		super(context, socket);
		this.dbm = DBManager.getInstance(context);
		this.asyncManager = AsyncManager.getInstance();
	}

	@Override
	protected void process(Context context, HttpRequest request, Socket socket, DefaultHttpServerConnection serverConnection) {
		Log.d(tag, "Started process(isStale=" + serverConnection.isStale() + ")");
		this.asyncManager.appendNetworkLog("Started process(isStale=" + serverConnection.isStale() + ")");
		for (Header reqHeader : request.getAllHeaders()) {
			Log.d(tag, "req:" + reqHeader.getName() + ": " + reqHeader.getValue());
			this.asyncManager.appendNetworkLog("req:" + reqHeader.getName() + ": " + reqHeader.getValue());
		}
		
		Uri uri = Uri.parse(request.getRequestLine().getUri());
		
		if (uri.getLastPathSegment().equals("play")) {
			String id = uri.getQueryParameter("id");
			
			ArrayList<DownloadProgress> aDp = this.dbm.getDownloadProgress("primarykey=?", new String[] {id}, "");
			if (aDp != null) {
				DownloadProgress dp = aDp.get(0);
				String contentType = this.dbm.getDownloadAttributeValue(dp.primarykey, "content-type");
				Log.d(tag, "found id=" + id + ", file=" + dp.filename);
				
				ArrayList<Header> respHeaders = new ArrayList<Header>();
				String respStr = "";
				
				int startBytes = 0;
				int lastBytes = dp.content_length;
				
				File f = new File(dp.filename);
				if (dp.content_length != f.length()) {
					lastBytes = (int) f.length();
					Log.w(tag, "content-length is not equal to file size, use filesize=" + String.valueOf(f.length()));
					this.asyncManager.appendNetworkLog("WARN content-length is not equal to file size, use filesize=" + String.valueOf(f.length()));
				}
				
				int newContentLength = lastBytes;
				respHeaders.add(new BasicHeader("Content-Type", contentType));
				respHeaders.add(new BasicHeader("Accept-Ranges", "bytes"));
				respHeaders.add(new BasicHeader("Connection", "close"));
				
				if (request.containsHeader("Range") == true) {
					
					Header rangeHeader = request.getFirstHeader("Range");
					int[] l = MediaHandler.getRanges(rangeHeader.getValue(), dp.content_length);
					if (l[0] != -1) {
						startBytes = l[0];
					}
					
					if (l[1] != -1) {
						lastBytes = l[1];
					}
				}
				
				newContentLength = lastBytes - startBytes;

				respHeaders.add(new BasicHeader("Content-Length", String.valueOf(newContentLength)));
				respHeaders.add(new BasicHeader("Content-Range", "bytes " + String.valueOf(startBytes) + "-" + String.valueOf(lastBytes) + "/" + String.valueOf(lastBytes+1)));
				
				respStr = STBHttpBuilderBase.createHttpResponse("1.1", "206", "Partial Content", respHeaders);
				Log.d(tag, "respStr=\r\n" + respStr);
				this.asyncManager.appendNetworkLog("respStr=\r\n" + respStr);
				byte[] buffer = respStr.getBytes();
				
				int position = startBytes;
				int readLen = 0;
				
				byte[] bb = null;
				
				try {
					socket.getOutputStream().write(buffer, 0, buffer.length);
					FileInputStream fs = new FileInputStream(dp.filename);
					
					fs.skip(startBytes);
							
					while (position < lastBytes) {
						boolean isLast = false;
						if (lastBytes-position < 8192) {
							Log.d(tag, "last one.. position=" + position + ", lastBytes=" + lastBytes);
							bb = new byte[(lastBytes-position)];
							isLast = true;
						} else {
							bb = new byte[8192];	
						}
						
						
						readLen = fs.read(bb, 0, bb.length);	
						
						if (readLen == -1) {
							Log.d(tag, "readLen=-1, position=" + position + ", lastBytes=" + lastBytes);
							break;
						}						

						socket.getOutputStream().write(bb, 0, readLen);
						socket.getOutputStream().flush();
						position += readLen;
						
					}
					
					//socket.getOutputStream().flush();
					fs.close();
					
					Log.d(tag, "Before end, isStale=" + serverConnection.isStale());
					
					
				} catch (Exception e) {
					String exceptionStr = "ERROR process(position=" + position + ", readLen=" + readLen + ", isStale=" + serverConnection.isStale() + ") - " + e.toString();
					this.asyncManager.appendNetworkLog(exceptionStr);
					Log.e(tag, "process(position=" + position + ", readLen=" + readLen + ", isStale=" + serverConnection.isStale() + ") - " + e.toString(), e);
					
										
				}
			}
			
		}
		
		
		this.asyncManager.appendNetworkLog("Ended process()");
		Log.d(tag, "Ended process()");
		
	}

}
